package com.example.demo1.temp;

import org.junit.Test;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ClassName: StreamAPITest
 * @Description: StreamApi练习
 * @Version: v1.0.0
 * @Author: tang
 * @Date: 2021/10/26
 * Modification History:
 * Date             Author      Version     Description
 * -------------------------------------------------------------
 * 2021/10/26      tang       v1.0.0      创建
 */
public class StreamApiTest {
        List<Person> persons = Arrays.asList(
                new Person(15,"张三", Person.Status.FREE,8888.88),
                new Person(20,"里斯",Person.Status.FREE,2222.88),
                new Person(60,"王武",Person.Status.FREE,345.88),
                new Person(36,"赵六", Person.Status.BUSY,6000.88),
                new Person(36,"赵六", Person.Status.VOCATION,18888.88),
                new Person(40,"陈其", Person.Status.BUSY,9635.88)

        );
    /**
     *Stream的三个操作步骤
     *
     *1.创建 Stream
     *
     *2.中间操作
     *
     *3.终止操作
     *
     *
    * */

    /**--------------------1 创建Stream------------------------------**/
    @Test
    public void test1(){
        //1.可以通过Collection系列提供的stream()或parallelStream()
        List<Person> p = new ArrayList<>();
        Stream<Person> stream1 = p.stream();
        //2.通过Arrays中的静态方法Stream() 获取数组流
        Person [] ps = new Person[10];
        Stream<Person> stream2 = Arrays.stream(ps);
        //3.通过Stream类中静态方法of()
        Stream<String> stream3 = Stream.of("aa","bb","cc");
        //4.创建无限流
        //迭代
        Stream<Integer> stream4 = Stream.iterate(0,(x)->x+2);
        //生成
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
    }

/**--------------------2 中间操作------------------------------**/
    /**-----------中间操作-》筛选切片-------------------------
     *
     *        筛选与切片
     *        filter --- 接收lambda从流中排除某元素
     *        limit  --- 截断流，使其元素不超过给定数量
     *        skip(n)--- 跳过元素，返回一个扔掉前n个元素的流，若流中元素不足n个，则返回一个空流，与limit(n)互补
     *        distinct-- 筛选，通过流生成元素的hashCode()和equals()去除重复元素
     *
     *    内部迭代：迭代由Stream API完成
     * **/
    @Test
    public void test2(){
        //中间操作不会执行任何操作
        Stream<Person> personStream = persons.stream()
                .filter((p) -> p.getAge() > 25)
                .limit(2)
                .skip(1);
        //终止操作：一次性执行全部内容，即“惰性求值”
        personStream.forEach(System.out::println);
    }
    @Test
    public void test3(){
        //中间操作不会执行任何操作
        persons.stream()
                .filter((p) -> p.getAge() > 25)
                .limit(2)
                .skip(1)
                .forEach(System.out::println);
    }

    /**-----------中间操作-》映射----------------------
     * 映射
     * map  -接收lambda，将元素转换成其他形式或提取信息，接收一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新的元素
     * flatMap -接收一个函数作为参数，将流中的每一个值都换成另一个流，然后把所有流连接成一个流
     *
     * */
    @Test
    public void test4(){
        List<String> list = Arrays.asList("aaa","bbb","ccc");
        list.stream().map(String::toUpperCase).forEach(System.out::println);
        System.out.println("--------------------------------------------");
        persons.stream().map(Person::getAge).forEach(System.out::println);
        System.out.println("--------------------------------------------");

        Stream<Stream<Character>> stream = list.stream().map(StreamApiTest::filterCharacter);
        //注意map返回的事stream流  filterCharacter返回的也是流   （此处将一个个流加入当前流中）
        stream.forEach(System.out::println);
        System.out.println("--------------------------------------------");

        Stream<Stream<Character>> stream2 = list.stream().map(StreamApiTest::filterCharacter);
        stream2.forEach(sm->{
           sm.forEach(System.out::println);
       });
       System.out.println("--------------------------------------------");

       /*注意当前是用的flatMap 此处将一个个元素加入当前流中）*/
        Stream<Character> stream3 = list.stream().flatMap(StreamApiTest::filterCharacter);
        stream3.forEach(System.out::print);
    }
    @Test
    public void test5(){
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        List list2 = new ArrayList();
        //
        list2.add(1);
        list2.add(list);
        list2.addAll(list);
        System.out.println(list2);

    }
    /**
     *
     * @Author tang
     * @Date 2021/10/26
     * @Param
     * @Return 字符串转成字符数字
     **/
    public  static  Stream<Character> filterCharacter(String str){
        List<Character> ch = new ArrayList<>();
        for (Character c :str.toCharArray()) {
            ch.add(c);
        }
        return ch.stream();
    }
    /**-----------中间操作-》映射----------------------
     * 排序
     * sorted -- 自然排序
     * sorted(Comparator com) -- 定制排序
     *
     * */
    @Test
    public void test6(){
        List<String> list = Arrays.asList("aa","bb","cc","dd");
        list.stream().sorted().forEach(System.out::println);
        persons.stream().sorted((p,q)->{
            if (p.getAge().equals(q.getAge())){
                return q.getName().compareTo(p.getName());
            }else{
                return q.getAge().compareTo(p.getAge());
            }
        }).forEach(System.out::println);
    }

/**--------------------3 终止操作------------------------------**/
    /**  查找与匹配
     *    allMatch 检查是否匹配所有元素
     *    anyMatch 检查是否至少匹配一个元素
     *    noneMatch 检查是否没有匹配所有元素
     *    FindFirst 返回第一个元素
     *    FindAny   返回当前流中任意一个元素
     *    count    返回流中元素的总个数
     *    max      返回流中最大值
     *    min       返回流中最小值
     *    forEach   遍历迭代
     **/
    @Test
    public void test7() {
        //1 查询集合所有元素是否匹配
        boolean b = persons.stream()
                .allMatch(p -> p.getStatus().equals(Person.Status.FREE));
        System.out.println(b);
        //2 查询集合是否有一个满足匹配要求
        boolean b2 = persons.stream()
                .anyMatch(p -> p.getStatus().equals(Person.Status.FREE));
        System.out.println(b2);
        //3 查询集合元素是否都不符合需求
        boolean b3 = persons.stream()
                .noneMatch(p -> p.getStatus().equals(Person.Status.FREE));
        System.out.println(b3);
        //4 查找第一个符合要求的元素
        Optional<Person> optional = persons.stream()
                .sorted((p1, p2) -> - Integer.compare(p1.getAge(), p2.getAge()))
                .findFirst();
        System.out.println(optional.get());
        //5 查找任意一个符合要求的元素
        Optional<Person> any = persons.stream()
                .sorted(Comparator.comparingInt(Person::getAge))
                .findAny();
        System.out.println(any.get());

        //6 流中元素个数
        long count = persons.stream().count();
        System.out.println(count);
        //7 流中年龄元素最小值
        Optional<Integer> min = persons.stream()
                .map(Person::getAge)
                .min(Integer::compare);
        System.out.println("最小值----------"+min.get());
        //流中名称元素最大值
        Optional<String> max = persons.stream().map(Person::getName)
                .max(String::compareTo);
        System.out.println("最大值----------"+max.get());
    }
    /**
     *    规约
     *    reduce(T identity,BinaryOperator) /reduce(BinaryOperator) 可以将流中元素反复结合起来，得到一个值
     *    收集
     *    collect 将流转换成其他形式，接收一个collect接口实现，用于给Stream中元素做汇总方法
     **/
    @Test
    public void test8(){
        List<Integer> list =  Arrays.asList(1,2,3,4,5,6,7,8);
        Integer reduce1 = list.stream().reduce(0, Integer::sum);
        System.out.println(reduce1);

        Optional<Integer> reduce = persons.stream()
                .map(Person::getAge)
                .reduce(Integer::sum);
        System.out.println(reduce.get());

    }

    @Test
    public void test9(){
        List<String> collect1 = persons.stream().map(Person::getName).collect(Collectors.toList());
        collect1.forEach(System.out::println);
        System.out.println("--------------------------------");
        Set<String> collect = persons.stream().map(Person::getName)
                .collect(Collectors.toSet());
        collect.forEach(System.out::println);
        System.out.println("--------------------------------");
        HashSet<String> collect2 = persons.stream().map(Person::getName).collect(Collectors.toCollection(HashSet::new));
        collect2.forEach(System.out::println);
    }

    @Test
    public void test10(){
        //总数
        Long count = persons.stream()
                .collect(Collectors.counting());
        System.out.println(count);

        //平均值
        Double avg = persons.stream()
                .collect(Collectors.averagingDouble(Person::getSalary));
        System.out.println(avg);

        //总和
        Double sum = persons.stream()
                .collect(Collectors.summingDouble(Person::getSalary));
        System.out.println(sum);

        //最大值
        Optional<Person> max = persons.stream()
                .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(max.get());

        //最小值
        Optional<Double> min = persons.stream()
                .map(Person::getSalary)
                .collect(Collectors.minBy(Double::compare));
        System.out.println(min.get());
    }

    @Test
    public void test04(){
        //分组
       Map<Integer, List<Person>> map = persons.stream()
                .collect(Collectors.groupingBy(Person::getAge));
        System.out.println(map);

        //多级分组
        Map<Person.Status, Map<String, List<Person>>> mapMap = persons.stream()
                .collect(Collectors.groupingBy(Person::getStatus, Collectors.groupingBy((e) -> {
                    if (e.getAge() > 35) {
                        return "开除";
                    } else {
                        return "继续加班";
                    }
                })));
        System.out.println(mapMap);

        //分区
        Map<Boolean, List<Person>> listMap = persons.stream()
                .collect(Collectors.partitioningBy((e) -> e.getSalary() > 4321));
        System.out.println(listMap);

    }
}
